#pragma once
#ifndef __G_VECTOR_3_H__
#define __G_VECTOR_3_H__

#include "GUtilities/GTypes.h"

namespace GMath
{

	class GVector3
	{
	public:
		static const GVector3	Zero;
		static const GVector3	One;
		static const GVector3	UnitX;
		static const GVector3	UnitY;
		static const GVector3	UnitZ;
		static const GVector3	Min;
		static const GVector3	Max;

		union
		{
			struct
			{
				float		x;
				float		y;
				float		z;
			};

			float			Arr[3];
		};

							GVector3();
							GVector3(float Vx, float Vy, float Vz);

							operator float* ();
							operator const float* ()const;

		float				Lenght() const;
		float				LenghtSqr() const;

		float				Distance(const GVector3& Vector) const;
		float				DistanceSqr(const GVector3& Vector) const;

		static void			Maximum(OUTPUT GVector3& Output, const GVector3& Vector1, const GVector3& Vector2);
		static void			Minimum(OUTPUT GVector3& Output, const GVector3& Vector1, const GVector3& Vector2);

		void				Absolute();
		static void			Absolute(OUTPUT GVector3& Output, const GVector3& Vector);

		void				Saturate();
		static void			Saturate(OUTPUT GVector3& Output, const GVector3& Vector);

		void				Clamp(const GVector3& LimitLow, const GVector3& LimitUp);
		static void			Clamp(OUTPUT GVector3& Output, const GVector3& Vector, const GVector3& LimitLow, const GVector3& LimitUp);

		void				Normalize();
		static void			Normalize(OUTPUT GVector3& Output, const GVector3& Vector);

		void				Scale(float Value);
		static void			Scale(OUTPUT GVector3& Output, const GVector3& Vector, float Value);
		
		void				Lerp(const GVector3& Vector, float Amount);
		static void			Lerp(OUTPUT GVector3& Output, const GVector3& VectorA, const GVector3& VectorB, float Amount);

		float				Dot(const GVector3& Vector) const;
		static float		Dot(const GVector3& VectorA, const GVector3& VectorB);

		void				Cross(const GVector3& Vector);
		static void			Cross(OUTPUT GVector3& Output, const GVector3& VectorA, const GVector3& VectorB);

		GVector3&			operator += (const GVector3& Vector);
		GVector3&			operator -= (const GVector3& Vector);
		GVector3&			operator *= (const GVector3& Vector);
		GVector3&			operator *= (const float Value);
		GVector3&			operator /= (const float Value);

		GVector3			operator + () const;
		GVector3			operator - () const;

		GVector3			operator + (const GVector3& Vector) const;
		GVector3			operator - (const GVector3& Vector) const;
		GVector3			operator * (const GVector3& Vector) const;
		GVector3			operator * (float Value) const;
		GVector3			operator / (float Value) const;

		bool				operator == (const GVector3& Vector) const;
		bool				operator != (const GVector3& Vector) const;

		friend GVector3		operator * (float Value, const GVector3& Vector);
		friend GVector3		operator / (float Value, const GVector3& Vector);

	};

}

#endif